package com.hly.poitool.word;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hwpf.usermodel.CharacterRun;
import org.apache.poi.hwpf.usermodel.Paragraph;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.hwpf.usermodel.Section;
import org.apache.poi.util.StringUtil;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import java.beans.PropertyDescriptor;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.*;

/**
 * @author : Jack Hao
 * @Date : 2022/4/16 13:47
 * @description : word 替换占位符中的内容
 */
public class PoiWordReplace {


    /**
     * 替换 文件 表格内的内容
     *
     * @param doc        document对象
     * @param replaceMap 要替换的内容
     * @return
     */
    public static XWPFDocument replaceTableText(XWPFDocument doc, Map<String, String> replaceMap) {

        if (doc == null) {
            return doc;
        }

        //文件中的所有的段落
        List<XWPFTable> tables = doc.getTables();

        if (tables == null || tables.isEmpty()) {
            return doc;
        }

        //遍历所有的段落
        for (int i = 0; i < tables.size(); i++) {
            //获取一个段落
            XWPFTable xwpfTable_i = tables.get(i);

            //获取段落的所有内容
            List<XWPFTableRow> rows = xwpfTable_i.getRows();
            if (rows == null || rows.isEmpty()) {
                continue;
            }

            //获取段落所有的内容
            for (int j = 0; j < rows.size(); j++) {
                XWPFTableRow row_j = rows.get(j);
                if (row_j == null) {
                    continue;
                }

                List<XWPFTableCell> cells = row_j.getTableCells();
                if (cells == null || cells.isEmpty()) {
                    continue;
                }
                for (int k = 0; k < cells.size(); k++) {
                    XWPFTableCell cell_k = cells.get(k);
                    replaceCell(cell_k, replaceMap);
                }
            }
        }
        return doc;
    }


    /**
     * 替换 文件 段落内的内容
     *
     * @param doc        document对象
     * @param replaceMap 要替换的内容
     * @return
     */
    public static XWPFDocument replaceParagraphText(XWPFDocument doc, Map<String, String> replaceMap) {

        if (doc == null) {
            return doc;
        }


        //文件中的所有的段落
        List<XWPFParagraph> paragraphs = doc.getParagraphs();

        if (paragraphs == null || paragraphs.isEmpty()) {
            return doc;
        }

        //遍历所有的段落
        for (int i = 0; i < paragraphs.size(); i++) {
            //获取一个段落
            XWPFParagraph xwpfParagraph_i = paragraphs.get(i);

            //获取段落的所有内容
            List<XWPFRun> runs = xwpfParagraph_i.getRuns();
            if (runs == null || runs.isEmpty()) {
                continue;
            }

            //获取段落所有的内容
            for (int j = 0; j < runs.size(); j++) {
                XWPFRun xwpfRun_j = runs.get(j);
                if (xwpfRun_j == null) {
                    continue;
                }
                replaceRun(xwpfParagraph_i, xwpfRun_j, j, replaceMap);
            }
        }
        return doc;
    }


    /**
     * 替换单元格的内容
     *
     * @param cell
     * @param replaceMap
     */
    private static void replaceCell(XWPFTableCell cell, Map<String, String> replaceMap) {
        String text = cell.getText();
        if (text == null || text.isEmpty() || text.isBlank()) {
            return;
        }
        boolean flag = false;
        Set<String> keySet = replaceMap.keySet();
        Iterator<String> keyIt = keySet.iterator();
        while (keyIt.hasNext()) {
            String key = keyIt.next();
            if (text.contains(key)) {
                String val = replaceMap.get(key);
                if (val == null || val.isEmpty()) {
                    val = "";
                }
                text = text.replaceAll(escapeExprSpecialWord(key), val);
                flag = true;
                //break;
            }
        }
        if (flag) {
            List<XWPFParagraph> paragraphs = cell.getParagraphs();
            for (int i = paragraphs.size() - 1; i > -1; i--) {
                cell.removeParagraph(i);
            }
            cell.setText(text);
        }
    }

    /**
     * 替换单元格的内容
     *
     * @param xwpfParagraph_i
     * @param xwpfRun_i
     * @param replaceMap
     */
    private static void replaceRun(XWPFParagraph xwpfParagraph_i, XWPFRun xwpfRun_i, int index, Map<String, String> replaceMap) {
        String text = xwpfRun_i.text();
        if (text == null || text.isEmpty() || text.isBlank()) {
            return;
        }
        boolean flag = false;
        Set<String> keySet = replaceMap.keySet();
        Iterator<String> keyIt = keySet.iterator();
        while (keyIt.hasNext()) {
            String key = keyIt.next();
            if (text.contains(key)) {
                String val = replaceMap.get(key);
                if (val == null || val.isEmpty()) {
                    val = "";
                }
                text = text.replaceAll(escapeExprSpecialWord(key), val);
                flag = true;
                //break;
            }
        }
        if (flag) {
            xwpfParagraph_i.removeRun(index);
            XWPFRun newRun = xwpfParagraph_i.insertNewRun(index);
            newRun.setText(text);
        }
    }


    /**
     * 转义特殊字符
     *
     * @param keyword
     * @return
     */
    public static String escapeExprSpecialWord(String keyword) {
        if (StringUtils.isNotBlank(keyword)) {
            String[] fbsArr = {"\\", "$", "(", ")", "*", "+", ".", "[", "]", "?", "^", "{", "}", "|"};
            for (String key : fbsArr) {
                if (keyword.contains(key)) {
                    keyword = keyword.replace(key, "\\" + key);
                }
            }
        }
        return keyword;
    }


    /**
     * 替换文件中的内容
     *
     * @param filePath  文件的路径
     * @param keyArrStr jsonarray 格式 占位符
     * @param valArrStr jsonarray 格式 替换后的字符串
     */
    public static void replaceText(String filePath, String keyArrStr, String valArrStr) {
        System.out.println("keyArrStr : "+keyArrStr);
        System.out.println("valArrStr : "+valArrStr);

        //拆分出来一部分文件
        InputStream is = null;
        OutputStream out = null;
        XWPFDocument doc = null;
        try {
            is = new FileInputStream(filePath);
            doc = new XWPFDocument(is);

            Map replaceMap = new HashMap();



            JSONArray keyArray = JSON.parseArray(keyArrStr);

            JSONArray valArray = JSON.parseArray(valArrStr);

//            JSONArray keyArray =  new JSONArray();
//            JSONArray valArray =  new JSONArray();
//            keyArray.add("${scf}");
//            keyArray.add("${pages}");
//            keyArray.add("${ver}");
//            keyArray.add("${ver-1}");
//            keyArray.add("${projectNum}");
//
//            valArray.add("机密");
//            valArray.add("3");
//            valArray.add("11");
//            valArray.add("10");
//            valArray.add("PPPP");
            //["${scf}","${pages}","${ver}","${ver-1}","${projectNum}"] ["机密","3","11","10","PPPP"]

            for (int i = 0; i < keyArray.size(); i++) {
                String key_i = keyArray.getString(i);
                String val_i = (String) valArray.get(i);
                replaceMap.put(key_i, val_i);
            }

            String str = "[\"${scf}\",\"${pages}\",\"${ver}\",\"${ver-1}\",\"${projectNum}\"]";

            //替换表格的内容
            replaceTableText(doc, replaceMap);

            //替换段落的内容
            replaceParagraphText(doc, replaceMap);

            out = new FileOutputStream(filePath);
            doc.write(out);
            out.flush();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (doc != null) {
                try {
                    doc.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {

        //            Map replaceMap = new HashMap();
//            replaceMap.put("${scf}", "机密");
//            replaceMap.put("${pages}", "10");
//            replaceMap.put("${ver}", "2022");
//            replaceMap.put("${ver-1}", "2021");
//            replaceMap.put("${projectNum}", "XAST-T008");



        String filePath = "D:\\svncode\\GW_2021x\\新建文件夹\\测试示例数据\\正常值范围\\自动生成正常值范围word文件\\XX卫星在轨运行遥测参数正常值范围.docx";


        JSONArray keyArray = new JSONArray();
        keyArray.add("${scf}");
        keyArray.add("${pages}");
        keyArray.add("${ver}");
        keyArray.add("${ver-1}");
        keyArray.add("${projectNum}");



        JSONArray valArray = new JSONArray();
        valArray.add("机密");
        valArray.add("10");
        valArray.add("2022");
        valArray.add("2021");
        valArray.add("XAST-T008");

        String keyStr = keyArray.toJSONString();
        String valStr = valArray.toJSONString();
//        System.out.println("keyStr : "+keyStr);
//        System.out.println("valStr : "+valStr);
//
//
//        String str1 = "[\"${scf}\",\"${pages}\",\"${ver}\",\"${ver-1}\",\"${projectNum}\"]";
//        String str2 = "[\"机密\",\"3\",\"11\",\"10\",\"PPPP\"]";


        replaceText( filePath,  keyStr,  valStr);


    }

}
